package com.demo.nio;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @author jasper
 */
@Service
@Slf4j
public class NioOp {
    public void channelRead() throws IOException {
        //1.创建一个RandomAccessFile（随机访问文件）对象，
        RandomAccessFile raf = new RandomAccessFile("/Users/jasper/data/test.sh", "rw");
        //通过RandomAccessFile对象的getChannel()方法。FileChannel是抽象类。
        FileChannel inChannel = raf.getChannel();
        //2.创建一个读数据缓冲区对象
        ByteBuffer buf = ByteBuffer.allocate(48);
        //创建一个写数据缓冲区对象
        ByteBuffer buf2 = ByteBuffer.allocate(48);
        //写入数据
        buf2.put("hello man\n".getBytes());
        buf2.flip();
        int read = inChannel.read(buf);

        while (read != -1) {
            //Buffer有两种模式，写模式和读模式。在写模式下调用flip()之后，Buffer从写模式变成读模式。
            buf.flip();
            //如果还有未读内容
            while (buf.hasRemaining()) {
                System.out.print((char) buf.get());
            }
            //清空缓存区
            buf.clear();
            read = inChannel.read(buf);
        }
        // 写到文件中了
        if (buf2.hasRemaining()) {
            inChannel.write(buf2);
        }
        inChannel.position(0);
        read = inChannel.read(buf);
        while (read != -1) {
            //Buffer有两种模式，写模式和读模式。在写模式下调用flip()之后，Buffer从写模式变成读模式。
            buf.flip();
            //如果还有未读内容
            while (buf.hasRemaining()) {
                System.out.print((char) buf.get());
            }
            //清空缓存区
            buf.clear();
            read = inChannel.read(buf);
        }
//        inChannel.close();
        //关闭RandomAccessFile（随机访问文件）对象
        raf.close();
    }

    public void socketClient() throws IOException {
        //1.通过SocketChannel的open()方法创建一个SocketChannel对象
        SocketChannel socketChannel = SocketChannel.open();
        //2.连接到远程服务器（连接此通道的socket）
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 3333));
        // 3.创建写数据缓存区对象
        ByteBuffer writeBuffer = ByteBuffer.allocate(128);
        writeBuffer.put("hello WebServer this is from WebClient".getBytes());
        writeBuffer.flip();
        socketChannel.write(writeBuffer);
        //创建读数据缓存区对象
        ByteBuffer readBuffer = ByteBuffer.allocate(128);
        socketChannel.read(readBuffer);
        //String 字符串常量，不可变；StringBuffer 字符串变量（线程安全），可变；StringBuilder 字符串变量（非线程安全），可变
        StringBuilder stringBuffer = new StringBuilder();
        //4.将Buffer从写模式变为可读模式
        readBuffer.flip();
        while (readBuffer.hasRemaining()) {
            stringBuffer.append((char) readBuffer.get());
        }
        System.out.println("从服务端接收到的数据：" + stringBuffer);

        socketChannel.close();
    }

    public void socketServer() {
        try {
            //1.通过ServerSocketChannel的open()方法创建一个ServerSocketChannel对象，open方法的作用：打开套接字通道
            ServerSocketChannel ssc = ServerSocketChannel.open();
            //2.通过ServerSocketChannel绑定ip地址和port(端口号)
            ssc.socket().bind(new InetSocketAddress("127.0.0.1", 3333));
            //通过ServerSocketChannelImpl的accept()方法创建一个SocketChannel对象用户从客户端读/写数据
            SocketChannel socketChannel = ssc.accept();
            //3.创建写数据的缓存区对象
            ByteBuffer writeBuffer = ByteBuffer.allocate(128);
            writeBuffer.put("hello WebClient this is from WebServer".getBytes());
            writeBuffer.flip();
            socketChannel.write(writeBuffer);
            //创建读数据的缓存区对象
            ByteBuffer readBuffer = ByteBuffer.allocate(128);
            //读取缓存区数据
            socketChannel.read(readBuffer);
            StringBuilder stringBuffer = new StringBuilder();
            //4.将Buffer从写模式变为可读模式
            readBuffer.flip();
            while (readBuffer.hasRemaining()) {
                stringBuffer.append((char) readBuffer.get());
            }
            System.out.println("从客户端接收到的数据：" + stringBuffer);
            socketChannel.close();
            ssc.close();
            //使用Paths工具类的get()方法创建
            Path path = Paths.get("D:\\XMind\\bcl-java.txt");
            System.out.println("文件名：" + path.getFileName());
            System.out.println("名称元素的数量：" + path.getNameCount());
            System.out.println("父路径：" + path.getParent());
            System.out.println("根路径：" + path.getRoot());
            System.out.println("是否是绝对路径：" + path.isAbsolute());
            //startsWith()方法的参数既可以是字符串也可以是Path对象
            System.out.println("是否是以为给定的路径D:开始：" + path.startsWith("D:\\"));
            System.out.println("该路径的字符串形式：" + path.toString());
            Path newDir = Files.createDirectory(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NioOp nioOp = new NioOp();
        try {
            nioOp.channelRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
